/*
 * Copyright 2023 Huawei Cloud Computing Technology Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.huawei.cloudphone.virtualdevice.sensor;

import static com.huawei.cloudphone.api.CloudPhoneParas.DEV_TYPE_SENSOR;
import static com.huawei.cloudphone.jniwrapper.JNIWrapper.SENSOR_DATA;
import static com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol.MSG_HEADER_LEN;

import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.util.Log;

import com.huawei.cloudphone.virtualdevice.common.IVirtualDeviceDataListener;
import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceManager;
import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol;
import com.huawei.cloudphone.virtualdevice.common.VirtualDeviceProtocol.MsgHeader;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class VirtualSensorManager extends VirtualDeviceManager {
    private static final String TAG = "VirtualSensorManager";

    public static final short OPT_SENSOR_ENABLE_REQ = 0x1;
    public static final short OPT_SENSOR_ENABLE_RSP = 0x1001;
    public static final short OPT_SENSOR_DISABLE_REQ = 0x2;
    public static final short OPT_SENSOR_DISABLE_RSP = 0x1002;
    public static final short OPT_SENSOR_STATUS_RSP = 0x1003;
    public static final short OPT_SENSOR_INFO_RSP = 0x1004;
    public static final short OPT_SENSOR_DATA = 0x10;

    private final int SENSOR_TYPE_WAKE_GESTURE = 23;
    private final int SENSOR_TYPE_GLANCE_GESTURE = 24;
    private final int SENSOR_TYPE_PICK_UP_GESTURE = 25;

    private VirtualSensor mVirtualSensor;
    private VirtualDeviceProtocol mVirtualDeviceProtocol;
    private Set<Integer> mOneShotSet = new HashSet<Integer>(Arrays.asList(
            Sensor.TYPE_SIGNIFICANT_MOTION, Sensor.TYPE_STATIONARY_DETECT, Sensor.TYPE_MOTION_DETECT,
            SENSOR_TYPE_WAKE_GESTURE, SENSOR_TYPE_GLANCE_GESTURE, SENSOR_TYPE_PICK_UP_GESTURE
    ));

    public VirtualSensorManager(VirtualDeviceProtocol virtualDeviceProtocol, SensorManager sensorManager) {
        mVirtualDeviceProtocol = virtualDeviceProtocol;
        mVirtualSensor = new VirtualSensor(sensorManager);
        mVirtualSensor.registerSensorDataListener(new SensorDataListener());
    }

    public void processMsg(MsgHeader header, byte[] body) {
        short sensorId = header.mDeviceId;
        switch (header.mOptType) {
            case OPT_SENSOR_ENABLE_RSP:
                Log.i(TAG, "processMsg: sensor id " + sensorId + " enable");
                mVirtualSensor.startProcess(sensorId);
                break;
            case OPT_SENSOR_DISABLE_RSP:
                Log.i(TAG, "processMsg: sensor id " + sensorId + " disable");
                mVirtualSensor.stopProcess(sensorId);
                break;
            case OPT_SENSOR_STATUS_RSP:
                int status = (body[0] << 8) | (body[1] & 0x0FF);
                Log.i(TAG, "processMsg: sensor id " + sensorId + " status " + status);
                MsgHeader msgHeader;
                if (status != 0) {
                    msgHeader = new MsgHeader(OPT_SENSOR_ENABLE_REQ, DEV_TYPE_SENSOR, sensorId, MSG_HEADER_LEN);
                    mVirtualDeviceProtocol.sendMsg(msgHeader, null, SENSOR_DATA);
                } else {
                    header = new MsgHeader(OPT_SENSOR_DISABLE_REQ, DEV_TYPE_SENSOR, sensorId, MSG_HEADER_LEN);
                    mVirtualDeviceProtocol.sendMsg(header, null, SENSOR_DATA);
                }
                break;
            default:
                Log.e(TAG, "processMsg: error opt type");
        }
    }

    public void start() {
        Log.e(TAG, "start");
        mVirtualSensor.start();
    }

    public void stop() {
        Log.e(TAG, "stop");
        mVirtualSensor.stop();
    }

    public String getSensorStatus() {
        return mVirtualSensor.getSensorStatus();
    }

    class SensorDataListener implements IVirtualDeviceDataListener {
        @Override
        public void onRecvData(Object... args) {
            SensorEvent sensorEvent = (SensorEvent) args[0];
            StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < sensorEvent.values.length; i++) {
                stringBuilder.append(Float.valueOf(sensorEvent.values[i]).toString() + ":");
            }
            stringBuilder.append(Integer.valueOf(sensorEvent.accuracy).toString() + ":");
            String body = stringBuilder.toString();
            int sensorId = sensorEvent.sensor.getType();
            int bodyLen = body.getBytes().length;
            int rspMsgLen = bodyLen + MSG_HEADER_LEN;
            MsgHeader header = new MsgHeader(OPT_SENSOR_DATA, DEV_TYPE_SENSOR, (short)sensorId, rspMsgLen);
            byte[] rspBody = new byte[bodyLen];
            System.arraycopy(body.getBytes(), 0, rspBody, 0, bodyLen);
            mVirtualDeviceProtocol.sendMsg(header, rspBody, SENSOR_DATA);

            // oneshot模式需主动发送0x2
            if (mOneShotSet.contains(sensorId)) {
                header = new MsgHeader(OPT_SENSOR_DISABLE_REQ, DEV_TYPE_SENSOR, (short)sensorId, MSG_HEADER_LEN);
                mVirtualDeviceProtocol.sendMsg(header, null, SENSOR_DATA);
                mVirtualSensor.stopProcess((short)sensorId);
            }
        }
    }
}